/* conio.h library for large systems - small embedded systems use clibrary.c instead */
#include "../src/interpreter.h"

#ifndef BUILTIN_MINI_STDLIB

#include <conio.h>
#include "pointerList.h"

#if 0
void ConioCgets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Pointer = cgets(Param[0]->Val->Pointer);
}

void ConioCputs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = cputs(Param[0]->Val->Pointer);
}
#endif

void ConioGetch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = getch();
}

void ConioGetche(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = getche();
}

void ConioKbhit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = kbhit();
}

void ConioPutch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = putch(Param[0]->Val->Integer);
}

void ConioUngetch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = ungetch(Param[0]->Val->Integer);
}

static PointerToPointerList * _list = NULL;


void _setCallback(void *key, void *value)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
	}
	setOrAddPointerToPointerList(_list,key,value);
}

void *_getCallback(void *key)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
	}
	return getPointerToPointerList(_list,key);
}

int ConioCallbackValue = 0;

extern void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
extern struct ValueType IntType;

int _callCallback(void *key)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
		return 0;
	}
	if (!VariableDefined(TableStrRegister("__callback_value")))
		VariableDefinePlatformVar(NULL, "__callback_value", &IntType, (union AnyValue *)&ConioCallbackValue, TRUE);

	char buf[512];

	sprintf(buf, "__callback_value = %s();", (char*)_getCallback(key)); 

	PicocParse("startup", buf, strlen(buf), TRUE, TRUE, FALSE);
	return ConioCallbackValue;
}

void ConioSetCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    _setCallback(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
}

void ConioGetCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Pointer = _getCallback(Param[0]->Val->Pointer);
}

void ConioCallCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = _callCallback(Param[0]->Val->Pointer);
}








/* all conio functions */
struct LibraryFunction ConioFunctions[] =
{
#if 0
    { ConioCgets,   "char * cgets(char *);" },
    { ConioCputs,   "int cputs(char *);" },
#endif
    { ConioGetch,   		"int getch();" },
    { ConioGetche,  		"int getche();" },
    { ConioKbhit,   		"int kbhit();" },
    { ConioPutch,   		"int putch(int);" },
    { ConioUngetch, 		"int ungetch(int);" },
    { ConioSetCallback, 	"void setCallback(void *, char *);" },
    { ConioGetCallback, 	"char* getCallback(void *);" },
    { ConioCallCallback, 	"int callCallback(void *);" },
    { NULL,         NULL }
};

static int ZeroValue = 0;


/* creates various system-dependent definitions */
void ConioSetupFunc(void)
{   

    /* define NULL, TRUE and FALSE */
    if (!VariableDefined(TableStrRegister("NULL")))
        VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE);
}


#endif

